<?php

namespace Budget\BudgetBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 * @ORM\Table(name="families")
 */
class Family
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="datetime")
     */
    protected $date_created;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    protected $date_deleted;

    /**
     * @ORM\OneToMany(targetEntity="Category", mappedBy="family")
     */
    protected $categories;

    /**
     * @ORM\OneToMany(targetEntity="Income", mappedBy="family")
     */
    protected $incomes;

    /**
     * @ORM\OneToMany(targetEntity="User", mappedBy="family")
     */
    protected $users;

    /**
     * @Assert\NotBlank()
     * @ORM\Column(type="string", length=50)
     */
    protected $name;
    /**
     *
     * @ORM\Column(type="integer", nullable=false, options={"default" = 1})
     */
    protected $firstDayOfMonth;
    /**
     *
     * @ORM\OneToMany(targetEntity="FamilyMonth", mappedBy="family")
     */
    protected $months;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->setDateCreated(new \DateTime());
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set date_created
     *
     * @param \DateTime $dateCreated
     * @return Family
     */
    public function setDateCreated($dateCreated)
    {
        $this->date_created = $dateCreated;

        return $this;
    }

    /**
     * Get date_created
     *
     * @return \DateTime
     */
    public function getDateCreated()
    {
        return $this->date_created;
    }

    /**
     * Set date_deleted
     *
     * @param \DateTime $dateDeleted
     * @return Family
     */
    public function setDateDeleted($dateDeleted)
    {
        $this->date_deleted = $dateDeleted;

        return $this;
    }

    /**
     * Get date_deleted
     *
     * @return \DateTime
     */
    public function getDateDeleted()
    {
        return $this->date_deleted;
    }

    /**
     * Add categories
     *
     * @param \Budget\BudgetBundle\Entity\Category $categories
     * @return Family
     */
    public function addCategory(\Budget\BudgetBundle\Entity\Category $categories)
    {
        $this->categories[] = $categories;

        return $this;
    }

    /**
     * Remove categories
     *
     * @param \Budget\BudgetBundle\Entity\Category $categories
     */
    public function removeCategory(\Budget\BudgetBundle\Entity\Category $categories)
    {
        $this->categories->removeElement($categories);
    }

    /**
     * Get categories
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getCategories()
    {
        return $this->categories;
    }

    /**
     * Add users
     *
     * @param \Budget\BudgetBundle\Entity\User $users
     * @return Family
     */
    public function addUser(\Budget\BudgetBundle\Entity\User $users)
    {
        $this->users[] = $users;

        return $this;
    }

    /**
     * Remove users
     *
     * @param \Budget\BudgetBundle\Entity\User $users
     */
    public function removeUser(\Budget\BudgetBundle\Entity\User $users)
    {
        $this->users->removeElement($users);
    }

    /**
     * Get users
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getUsers()
    {
        return $this->users;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Family
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Add incomes
     *
     * @param \Budget\BudgetBundle\Entity\Income $incomes
     * @return Family
     */
    public function addIncome(\Budget\BudgetBundle\Entity\Income $incomes)
    {
        $this->incomes[] = $incomes;

        return $this;
    }

    /**
     * Remove incomes
     *
     * @param \Budget\BudgetBundle\Entity\Income $incomes
     */
    public function removeIncome(\Budget\BudgetBundle\Entity\Income $incomes)
    {
        $this->incomes->removeElement($incomes);
    }

    /**
     * Get incomes
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getIncomes()
    {
        return $this->incomes;
    }

    /**
     * Set firstDayOfMonth
     *
     * @param integer $firstDayOfMonth
     * @return Family
     */
    public function setFirstDayOfMonth($firstDayOfMonth)
    {
        $this->firstDayOfMonth = $firstDayOfMonth;

        return $this;
    }

    /**
     * Get firstDayOfMonth
     *
     * @return integer
     */
    public function getFirstDayOfMonth()
    {
        return $this->firstDayOfMonth;
    }

    /**
     * Returns Month start date for given year and month from family months
     * If family month doesn't exists - return current year-month + first day od month property
     * @param type $year
     * @param type $month
     * @return \DateTime
     */
    public function getStartMonthDate($year = null, $month = null)
    {
        $date = new \DateTime();

        $paramsSet = is_null($year) && is_null($month);
        if (is_null($year)) {
            $year = date('Y');
        }

        if (is_null($month)) {
            $month = date('n');
        }

        $today = date('j');
        $date->setDate($year, $month, $today);
        if ($today < $this->getFirstDayOfMonth() && $paramsSet) {
            $date->modify('-1 month');//the billing period is not finished yet
        }

        $familyMonth = $this->findMonth($date->format('Y'), $date->format('n'));
        if (!is_null($familyMonth)) {
            return $familyMonth->getStart();
        }

        $day = $this->getFirstDayOfMonth();

        $date->setDate($year, $month, $day);

        return $date;
    }

    /**
     *
     * @param type $year
     * @param type $month
     * @return type
     */
    public function getEndMonthDate($year = null, $month = null)
    {
        $paramsSet = is_null($year) && is_null($month);
        if (is_null($year)) {
            $year = date('Y');
        }

        if (is_null($month)) {
            $month = date('n');
        }

        $date  = new \DateTime();
        $today = date('j');
        $date->setDate($year, $month, $today);
        if ($today < $this->getFirstDayOfMonth() && $paramsSet) {
            $date->modify('-1 month');//the billing period is not finished yet
        }

        $familyMonth = $this->findMonth($date->format('Y'), $date->format('n'));
        if (!is_null($familyMonth)) {
            return $familyMonth->getEnd();
        }

        $lastDate = clone $this->getStartMonthDate($year, $month);

        $lastDate->modify('+1 month');
        $lastDate->modify('-1 day');

        return $lastDate;
    }

    /**
     * Finds
     * @param type $year
     * @param type $month
     * @return null
     */
    public function findMonth($year, $month)
    {
        $months = $this->getMonths();

        foreach ($months as $familyMonth) {
            if ($familyMonth->getYear() == $year && $familyMonth->getMonth() == $month) {
                return $familyMonth;
            }
        }

        return null;
    }

    /**
     * Add months
     *
     * @param \Budget\BudgetBundle\Entity\FamilyMonth $months
     * @return Family
     */
    public function addMonth(\Budget\BudgetBundle\Entity\FamilyMonth $months)
    {
        $this->months[] = $months;

        return $this;
    }

    /**
     * Remove months
     *
     * @param \Budget\BudgetBundle\Entity\FamilyMonth $months
     */
    public function removeMonth(\Budget\BudgetBundle\Entity\FamilyMonth $months)
    {
        $this->months->removeElement($months);
    }

    /**
     * Get months
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getMonths()
    {
        return $this->months;
    }
}
